package org.iabako.server.serviceimpl.business;

import org.iabako.server.dao.business.FinanceDAO;
import org.iabako.server.tools.ServerTools;
import org.iabako.shared.dto.FinancesBalance;
import org.iabako.shared.dto.FinancesChartData;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.iservice.business.FinanceService;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by jose on 12/11/14.
 */

@org.springframework.stereotype.Service("financeService")
public class FinanceServiceImpl implements FinanceService {

    @Autowired
    private FinanceDAO financeDAO;

    public FinancesBalance getFinancesBalanceByDay(String ddMMyyyy) {
        return financeDAO.getFinancesBalanceByDay(GenericTools.getDate(ddMMyyyy));
    }

    public FinancesBalance getFinancesBalanceByMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(GenericTools.getDateWithoutTime());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.MONTH, month);
        return financeDAO.getFinancesBalanceByMonth(calendar.getTime());
    }

    public FinancesBalance getFinancesBalanceByYear(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(GenericTools.getDateWithoutTime());
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return financeDAO.getFinancesBalanceByYear(calendar.getTime());
    }

    public List<Double> getPendingResume(Enterprise enterprise) {
        List<Double> result = new ArrayList<Double>(3);
        result.add(new Double(financeDAO.getNumberOfClientsWithPastInstallments(enterprise)));
        result.add(financeDAO.getPastInstallmentsSum(enterprise));
        result.add(financeDAO.getPendingExpensesSum(enterprise));

        return result;
    }

    public List<Double> getPendingResume() {
        List<Double> result = new ArrayList<Double>(3);
        result.add(new Double(financeDAO.getNumberOfClientsWithPastInstallments()));
        result.add(financeDAO.getPastInstallmentsSum());
        result.add(financeDAO.getPendingExpensesSum());

        return result;
    }

    private FinancesChartData getIncomeOutcomeFinancesChartData(Date date, Date datePlusOne) {
        FinancesChartData financesChartData = new FinancesChartData();
        FinancesBalance financesBalance = financeDAO.getFinancesBalance(date, datePlusOne, true);
        financesChartData.addValue(financesBalance.getSalesPayed());
        financesChartData.addValue(financesBalance.getExpensesPayed());

        return financesChartData;
    }

    public List<FinancesChartData> getSalesExpensesForLastMonths(String ddMMyyyy) {
        List<FinancesChartData> datas = new ArrayList<FinancesChartData>();
        ServerTools serverTools = new ServerTools();

        Date finalDate = GenericTools.getDate(ddMMyyyy);

        Date firstDate = financeDAO.getFirstDate();
        Date initialDate = serverTools.addMonthsToDate(finalDate, -12);

        if (initialDate.compareTo(firstDate) < 0) {
            initialDate = firstDate;
        }

        Long interval = (finalDate.getTime() - initialDate.getTime()) / 1000 / 60 / 60 / 24;
        Long offset = 1L;
        if (interval > 5) {
            offset = interval / 5 + 2;
        }

        Date date = initialDate;

        while (date.compareTo(finalDate) < 0) {
            FinancesChartData financesChartData = getIncomeOutcomeFinancesChartData(initialDate, serverTools.addDaysToDate(date, 1));
            financesChartData.setTitle(GenericTools.formatSmallDate(date));
            financesChartData.setTooltipPrefix(GenericTools.formatDate(date) + "\n");
            //add two tooltips
            datas.add(financesChartData);
            date = serverTools.addDaysToDate(date, offset.intValue());
        }
        FinancesChartData financesChartData = getIncomeOutcomeFinancesChartData(initialDate, serverTools.addDaysToDate(finalDate, 1));
        financesChartData.setTooltipPrefix(GenericTools.formatDate(date) + "\n");
        //add two tooltips
        financesChartData.setTitle(GenericTools.formatSmallDate(finalDate));
        datas.add(financesChartData);

        return datas;
    }

    public List<FinancesChartData> getSalesExpensesForLastYears(int lastYear) {
        List<FinancesChartData> datas = new ArrayList<FinancesChartData>();
        ServerTools serverTools = new ServerTools();

        Date firstDate = financeDAO.getFirstDate();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(firstDate);
        int firstYear = calendar.get(Calendar.YEAR);

        calendar.set(Calendar.YEAR, lastYear);
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        Date finalDate = calendar.getTime();

        int interval = lastYear - firstYear;
        if (interval > 3) {
            interval = 3;
        }

        Date date = new ServerTools().addYearsToDate(finalDate, interval * -1);

        while (date.compareTo(finalDate) < 0) {
            FinancesChartData financesChartData = getIncomeOutcomeFinancesChartData(date, serverTools.addYearsToDate(date, 1));
            financesChartData.setTitle(GenericTools.getYear(date));
            financesChartData.setTooltipPrefix(GenericTools.getYear(date) + "\n");
            //profit value
            datas.add(financesChartData);

            date = serverTools.addYearsToDate(date, 1);
        }
        FinancesChartData financesChartData = getIncomeOutcomeFinancesChartData(date, serverTools.addYearsToDate(date, 1));
        financesChartData.setTitle(GenericTools.getYear(date));
        financesChartData.setTooltipPrefix(GenericTools.getYear(date) + "\n");
        datas.add(financesChartData);

        return datas;
    }

    public List<FinancesChartData> getExpensesByCategoryForMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(GenericTools.getDateWithoutTime());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.MONTH, month);
        Date initialDate = calendar.getTime();
        Date finalDate = new ServerTools().addMonthsToDate(initialDate, 1);

        return financeDAO.getFinancesChartDataForPayedExpenses(initialDate, finalDate);
    }

    public List<FinancesChartData> getExpensesByCategoryForYear(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(GenericTools.getDateWithoutTime());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.YEAR, year);
        Date initialDate = calendar.getTime();
        Date finalDate = new ServerTools().addYearsToDate(initialDate, 1);

        return financeDAO.getFinancesChartDataForPayedExpenses(initialDate, finalDate);
    }

    public List<FinancesChartData> getBestClients() {
        return financeDAO.getBestClients();
    }

    public List<FinancesChartData> getBestServices() {
        return financeDAO.getBestServices();
    }

    public List<FinancesChartData> getWorstClients() {
        return financeDAO.getWorstClients();
    }

    public List<FinancesChartData> getBestProducts() {
        return financeDAO.getBestProducts();
    }

}
